/**
 * @author :    hippo
 * @date :      2023-08-03
 * @copyright   Apache 2.0
*/

#ifndef _WEBSERVER_H
#define _WEBSERVER_H

#include <unordered_map>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "server/epoller.h"
#include "log/log.h"
#include "timer/heaptimer.h"
#include "pool/sql_conn_pool.h"
#include "pool/thread_pool.h"
#include "pool/sql_conn_RAII.h"
#include "http/http_conn.h"

class WebServer {
private:
    static const int MAX_FD = 65536;

    int port_;
    bool open_linger_;
    int timeout_ms_;
    bool is_close_;
    int listen_fd_;
    char* src_dir_;

    uint32_t listen_event_;
    uint32_t conn_event_;

    std::unique_ptr<HeapTimer> timer_;
    std::unique_ptr<ThreadPool> thread_pool_;
    std::unique_ptr<Epoller> epoller_;
    std::unordered_map<int, HttpConn> user_;

public:
    WebServer(
        int port,
        int trig_mode,
        int timeout_ms,
        int opt_linger,
        int sql_port,
        const char* sql_user,
        const char* sql_pwd,
        const char* db_name,
        int conn_pool_num,
        int thread_num,
        bool open_log,
        int log_level,
        int log_que_size
    );
    ~WenServer();
    void Start();

private:
    bool InitSocket();
    void InitEventMode(int trig_mode);
    void AddClient(int fd, sockaddr_in addr);

    void DealListen();
    void DealWrite(HttpConn* client);
    void DealRead(HttpConn* client);

    void SendError(int fd, const char* info);
    void ExtentTime(HttpConn* client);
    void CloseConn(HttpConn* client);

    void OnRead(HttpConn* client);
    void OnWrite(HttpConn* client);
    void OnProcess(HttpConn* client);

    static int SetFdNonblock(int fd);
};

#endif // _WEBSERVER_H